package com.googlecode.cgpwall;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Random;

import com.admob.android.ads.AdManager;
import com.admob.android.ads.AdView;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.app.WallpaperManager;
import android.app.AlertDialog.Builder;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.graphics.Bitmap;
import android.text.Html;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

public class CgpWall extends Activity {

	public static final int NODELENGTH = 10;
	public static final int NUM_FUNCTIONS = 11;
    public static final int POP_SIZE = 6;
    public static final int TOP = 0;
    public static final int BOTTOM = 1;
    public static final int PROGRESS_DIALOG = 0;
    public static final int SAVINGTOP_DIALOG = 1;
    public static final int SAVINGBOTTOM_DIALOG = 2;    
    public static final int SETTINGTOP_DIALOG = 3;
    public static final int SETTINGBOTTOM_DIALOG = 4;    
    public static final int WIDTH_THUMB = 500;
    public static final int HEIGHT_THUMB = 360;
    
    private int counter = 0;
    private final Random random = new Random();
    private ImageView[] images = new ImageView[2];
    private Bitmap[] bMap = new Bitmap[2];
    private int[][] nodes = new int[2][];

    private ProgressThread progressThread;
    private SavingThread savingThread;
    private ProgressDialog progressDialog;
    private ProgressDialog savingDialog;
    
    private ArrayList<int[]> wallpapers = new ArrayList<int[]>();
    private ArrayList<int[]> temp_wallpapers = new ArrayList<int[]>();
	private EventDataSQLHelper nodeData;
    private AdView adView;
    private WallpaperManager wm;
    
    /***** Listeners to clicks *****/
    
    private ImageView.OnLongClickListener topsave = new ImageView.OnLongClickListener () {
    	
		// On press, save to the gallery or set as wallpaper.
		
 		@Override
		public boolean onLongClick(View arg0) {
    		showSave(TOP);  
			return true;
		}
	};

    private ImageView.OnLongClickListener bottomsave = new ImageView.OnLongClickListener () {
    	
		// On press, save to the gallery or set as wallpaper.
		
 		@Override
		public boolean onLongClick(View arg0) {
    		showSave(BOTTOM);
			return true;
		}
	};

	private OnClickListener resetclick = new OnClickListener() { 

		@Override
		public void onClick(DialogInterface arg0, int arg1) {
			resetImages();
		}
	};
	
	private ImageView.OnClickListener top = new ImageView.OnClickListener () {
    	
		// On click, add nodes of item to temp_wallpapers to keep track of it. Reset items.
    	// Once number of items clicked equals population size, add selected items to real wallpapers array.
		
    	@Override
		public void onClick(View arg0) {
			if (temp_wallpapers.size() < POP_SIZE){
				temp_wallpapers.add(nodes[0]);
			}
			if (temp_wallpapers.size() == POP_SIZE){
				for (int u =0; u < temp_wallpapers.size(); u++){
					wallpapers.add(u, temp_wallpapers.get(u));
				}
			}
			counter++;
			resetImages();
		}
	};
    private ImageView.OnClickListener bottom = new ImageView.OnClickListener () {
		
		@Override
		public void onClick(View arg0) {
			if (temp_wallpapers.size() < POP_SIZE){
				temp_wallpapers.add(nodes[1]);
			}
			if (temp_wallpapers.size() == POP_SIZE){
				for (int u =0; u < temp_wallpapers.size(); u++){
					wallpapers.add(u, temp_wallpapers.get(u));
				}
			}
			counter++;
			resetImages();
		}
	}; 
    
	/** 
	 * Called when activity is launched 
	 */
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        nodeData = new EventDataSQLHelper(this);
        images[0] = (ImageView) this.findViewById(R.id.mypic1);
        images[1] = (ImageView) this.findViewById(R.id.mypic2);
        addListeners();

		// remove when releasing
		//AdManager.setTestDevices( new String[] { AdManager.TEST_EMULATOR, "DE5AF39D350C1E2CBF7E873DED739E9B" } );

		adView = (AdView)findViewById(R.id.ad);
		wm = WallpaperManager.getInstance(this);
		initializeWallpaper();
		adView.requestFreshAd();	
    }
    
    /** 
     * If this is first time opening app, make all new nodes. 
     * Else, get nodes from database.
     */
    public void initializeWallpaper() {
    	// if database not set
		SQLiteDatabase db = nodeData.getReadableDatabase();
		
		Cursor cursor = db.query(EventDataSQLHelper.TABLE, null, null, null, null, null, null);
		startManagingCursor(cursor);
		while (cursor.moveToNext()) {
			wallpapers.add(stringToNode(cursor.getString(1)));
			Log.d("Initialize", "Loading " + cursor.getString(1));
		}
		cursor.close();
		db.close();
		boolean empty = wallpapers.size() == 0;
		fillWallpaper();
		if (empty) {
			showHelp(resetclick);
		} else {
			resetImages();
		}
    }
    
    /**
     * Fill up the wallpapers ArrayList with random nodes
     */
    public void fillWallpaper() {
		while (wallpapers.size() < POP_SIZE * 2) {
			wallpapers.add(node());
		}
    }
    
    /**
     * Wipes the saved population from the database
     */
    public void wipeDB() {
		SQLiteDatabase db = nodeData.getReadableDatabase();
		db.delete(EventDataSQLHelper.TABLE, null, null);
		db.close();
    }
    
    /**
     * Saves the current wallpaper ArrayList to the database
     */
    public void saveToDB() {
    	wipeDB();
		SQLiteDatabase db = nodeData.getReadableDatabase();
		ContentValues values = new ContentValues();
		for (int i = 0; i < wallpapers.size(); i++) {
			values.put(EventDataSQLHelper.NODE, nodeToString(wallpapers.get(i)));
			try {				
				db.insertOrThrow(EventDataSQLHelper.TABLE, null, values);
				Log.d("AddToDB", nodeToString(wallpapers.get(i)));
			} catch (SQLException e) {
				Log.d("AddToDB", "" + e.getMessage());
			}
		}
		db.close();
    }
    
    /**
     * Converts a node into a string for the database
     * @param node an int[] for a node
     * @return the String for a node
     */
    public String nodeToString(int[] node) {
    	String log = "";
    	for (int l = 0; l < node.length - 1; l++){
    		log += node[l] + " ";
    	}
    	return log + node[node.length - 1];
    }
    
    /**
     * converts a string to a node from the database
     * @param node a String node rep from the db
     * @return an int[] array
     */
    public int[] stringToNode(String node) {
    	String[] temp = node.split("\\s");
    	int[] stuff = new int[temp.length];
    	for (int i = 0; i < temp.length; i++) {
    		stuff[i] = Integer.parseInt(temp[i]);
    	}
    	return stuff;
    }
    
    /**
     * Create null clicklisteners so things can't be clicked while loading.
     * Then show progress of generating two new thumbnail images.
     */
    public void resetImages() {
    	images[TOP].setOnClickListener(null);
    	images[BOTTOM].setOnClickListener(null);
    	images[TOP].setOnLongClickListener(null);
    	images[BOTTOM].setOnLongClickListener(null);
		showDialog(PROGRESS_DIALOG);
    }
    
    /**
     * Adds back the listeners to the images
     */
    public void addListeners() {
		images[TOP].setOnClickListener(top);	
		images[BOTTOM].setOnClickListener(bottom);
		images[TOP].setOnLongClickListener(topsave);	
		images[BOTTOM].setOnLongClickListener(bottomsave);
    }

    /** 
     * Creates a new node. Node = list of integers divided into groups of three.
     * First two ints are indexes to outputs array to use in function call to generate more outputs.
     * Last int is function identifier. 11 functions as of presentation. 
     * Last group in node define output indexes which are to be used as rgb values for a pixel.
     */
    public int[] node(){
    	
    	ArrayList<Integer> node = new ArrayList<Integer>();
    	int[] node_final = new int[(NODELENGTH * 3) + 3];
    	int count = 2;
    	for (int i = 0; i < NODELENGTH; i++){
    		int h = random.nextInt(NUM_FUNCTIONS);  		
    		int j = random.nextInt(count);
    		int k = random.nextInt(count);
    		
    		node.add(j);
    		node.add(k);
    		node.add(h);
    		count++;
    	}
    	
    	/*Instead there will be three separate pointers that can point to any node and take that value as the output*/
    	// Don't want inputs' indexes cuz then will get numbers > 255.
    	int g = random.nextInt(count - 2) + 2;
    	int d = random.nextInt(count - 2) + 2;
    	int r = random.nextInt(count - 2) + 2;
    	node.add(g);
    	node.add(d);
    	node.add(r);
    	for (int l = 0; l < node_final.length; l++){
    		node_final[l] = node.get(l).intValue();
    	}
    	Log.d("NODE", "Generated new node " + nodeToString(node_final));
    	return node_final;
    }
    
    /**
     * Builds array of integers outputs. First two items in array are x,y
     * After an output is created for each group in the node, get the outputs as divided by last
     * three integers in node to use as rgb values. Return this.
     * @param x position of x pixel
     * @param y position of y pixel
     * @param node array created to represent functions
     * @param values place to store function output
     * @return the rgb integers for the pixel
     */
    public int[] rgbvalues(int x, int y, int[] node, int[] values){
    	values[0] = x;
    	values[1] = y;
    	int nodeplace = 0;
    	for(int i = 2; i < values.length; i++){
    		int f = values[node[nodeplace++]];
    		int g = values[node[nodeplace++]];
    		int function = node[nodeplace++];
    		if (function == 0) {
				values[i] = (f | g);
			}
			else if (function == 1) {
				values[i] = (f % (g + 1));
			}
			else if (function == 2) {
				values[i] = ((int)(f / 3.0));
			}
			else if (function == 3) {
				values[i]= (int)(Math.abs(Math.cos(Math.toRadians(f))*255));
			}
			else if (function == 4) {
				values[i] = (int)(Math.abs(Math.sin(Math.toRadians(f))*255));
			}
			else if (function == 5) {
				values[i] = (int)(Math.abs(Math.atan(Math.toRadians(f)) / (Math.PI / 2) * 255));
			}
			else if (function == 6) {
				values[i] = ((f & g));
			}
			else if (function == 7) {
				values[i] = (f + g);
			}
			else if (function == 8) {
				values[i] = (f == g) ? f : (f > g) ? f - g : g - f;
			}
			else if (function == 9) {
				values[i] = (int)(Math.abs(255 - f));
			}
			else if (function == 10) {
				values[i] = (int)Math.sqrt(Math.pow(f - 400, 2.0) + Math.pow(g - 400, 2.0));
			}
			else {
				Log.e("OOPS", "function choice of " + Integer.toString(function));
			}
    	}
    	
    	int[] rgb = new int[3];
    	rgb[0] = values[node[node.length-3]] % 255;
    	rgb[1] = values[node[node.length-2]] % 255;
    	rgb[2] = values[node[node.length-1]] % 255;
    	return rgb;
    }
    
    /**
     * gets a random point to split genotype for crossover
     * @return random cutpoint
     */
    public int getCutPoint(){
    	int cut = random.nextInt((NODELENGTH * 3));
    	if (cut % 3 == 1){
    		return cut + 2;
    	}
    	else if (cut % 3 == 2){
    		return cut + 1;
    	}
    	else {
    		return cut;
    	}
    	
    }
    
    /** 
     * Takes wallpapers that were selected in last round and cross them over and two points.
     * Also adds new backgrounds to make population, choose 1/2 you like.
     */
    public void crossover(){
    	
    	//int cut2 =  ((NODELENGTH * 3 + 1) / 3) + cut;
    	for (int g = 0; g < (wallpapers.size() - 1); g += 2){
    		int cut = getCutPoint();
    		int[] parent1 = wallpapers.get(g);
    		int[] parent2 = wallpapers.get(g + 1);
    		
    		int[] child1 = new int[parent1.length];
    		int[] child2 = new int[parent2.length];
    		for (int i = 0; i < (cut); i++){
    			child1[i] = parent1[i];
    			child2[i] = parent2[i];
    		}
    		for (int j = cut; j < parent1.length; j++){
    			child1[j] = parent2[j];
    			child2[j] = parent1[j];
    		}
    		
    		
    		wallpapers.set(g, child1);
    		wallpapers.set(g + 1, child2);
    	}
    	for (int d = 0; d < (wallpapers.size() * 2); d++){
    		if (d < wallpapers.size()){
    			temp_wallpapers.add(wallpapers.get(d));
    		}
    		else {
    			temp_wallpapers.add(node());
    		}
    	}
    	wallpapers.clear();
    	for (int u = 0; u < temp_wallpapers.size(); u++){
			wallpapers.add(u, temp_wallpapers.get(u));
		}
    	temp_wallpapers.clear();
    }

    /**
     * If point picked + 1 in node / 3 = 0, then mutate between 0 and 10
     * If point picked is NODELENGTH-1, -2, or -3, pick # between 2 and NODELENGTH at random to change it.
     * mutates input now as well to an output that has come before it.
     * Randomly selects how many places in the the genotype it should mutate. Between 0-19 as example. For genotype
   	 *   with 20 nodes, there's 63 places to potentially mutate.
     *   also, this mutates every child and new genotype created in crossover. But I guess a genotype does have a small
     *   probability of e being 0, thus not getting mutated, huh? 
     */
    public void mutation(){
   
     	for (int[] temp : wallpapers) {
    		int e = random.nextInt(20);
    		for (int y = 0; y < e; y++){
    			int h = random.nextInt(temp.length);
    			//Log.d("MUT", "selected index " + h);
    			if (h == temp.length - 1 || h == temp.length - 2 || h == temp.length - 3){
    				int newrgb = random.nextInt(NODELENGTH) + 2;
    				//Log.d("MUT", "Picking new node " + newrgb);
    				temp[h] = newrgb;
    			} else if (((h + 1) % 3) == 0){
    				int newfunction = random.nextInt(NUM_FUNCTIONS);
    				//Log.d("MUT", "Picking new function " + newfunction);
    				temp[h] = newfunction;
    			} else {
    				int newinput = random.nextInt(h / 3 +1);
    				temp[h] = newinput;
    				//Log.d("MUT", "Picking new input " + newinput);
    			}
    		}
    	}
    }
    
    /**
     * For each thumbnail, randomly choose node from wallpapers. This makes it so the same ones are not crossed
     * over each time as the order will be switched up each time. 
     * @return a random selection from the wallpaper
     */
    public int[] getNode(){    	
     	int u = random.nextInt((wallpapers.size()));
    	int[] temp = wallpapers.get(u);
    	wallpapers.remove(u);
    	Log.d("SIZE", Integer.toString(wallpapers.size()));
    	return temp;   	
    }

    /******************* PROGRESS DIALOG *****************/
    
    protected Dialog onCreateDialog(int id) {
        switch(id) {
        case PROGRESS_DIALOG:
            progressDialog = new ProgressDialog(CgpWall.this);
            progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            progressDialog.setMessage("Learning Your Preferences...");
            progressThread = new ProgressThread(handler, wm.getDesiredMinimumHeight()/3, wm.getDesiredMinimumWidth()/3);
            progressThread.start();
            Log.d("PD", "Creating new process dialog and thread");
            return progressDialog;
        case SAVINGTOP_DIALOG:
            savingDialog = new ProgressDialog(CgpWall.this);
            savingDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            savingDialog.setMessage("Saving Top In Gallery...");
            savingThread = new SavingThread(shandler, TOP, wm.getDesiredMinimumHeight(), wm.getDesiredMinimumWidth(), false);
            savingThread.start();
            Log.d("PD", "Creating new savingtop dialog and thread");
            return savingDialog;
        case SAVINGBOTTOM_DIALOG:
            savingDialog = new ProgressDialog(CgpWall.this);
            savingDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            savingDialog.setMessage("Saving Bottom In Gallery...");
            savingThread = new SavingThread(bhandler, BOTTOM, wm.getDesiredMinimumHeight(), wm.getDesiredMinimumWidth(), false);
            savingThread.start();
            Log.d("PD", "Creating new savingbottom dialog and thread");
            return savingDialog;
        case SETTINGTOP_DIALOG:
            savingDialog = new ProgressDialog(CgpWall.this);
            savingDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            savingDialog.setMessage("Setting Top As Wallpaper...");
            savingThread = new SavingThread(ssethandler, TOP, wm.getDesiredMinimumHeight(), wm.getDesiredMinimumWidth(), true);
            savingThread.start();
            Log.d("PD", "Creating new savingtop dialog and thread");
            return savingDialog;
        case SETTINGBOTTOM_DIALOG:
            savingDialog = new ProgressDialog(CgpWall.this);
            savingDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            savingDialog.setMessage("Setting Bottom As Wallpaper...");
            savingThread = new SavingThread(bsethandler, BOTTOM, wm.getDesiredMinimumHeight(), wm.getDesiredMinimumWidth(), true);
            savingThread.start();
            Log.d("PD", "Creating new savingbottom dialog and thread");
            return savingDialog;
        default:
            return null;
        }
    }

    /**
     * Define the Handler that receives messages from the thread and update the progress
     */
    final Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            int total = msg.getData().getInt("total");
            progressDialog.setProgress(total);
            if (total >= 100){
                removeDialog(PROGRESS_DIALOG);
                for (int r = 0; r < 2; r++) {
                	images[r].setImageBitmap(bMap[r]);
                }
        		addListeners();
            }
        }
    };

    /**
     * Define the Handler that receives messages from the thread and update the progress
     */
    final Handler shandler = new Handler() {
        public void handleMessage(Message msg) {
            int total = msg.getData().getInt("total");
            savingDialog.setProgress(total);
            if (total >= 100){
                removeDialog(SAVINGTOP_DIALOG);
				Toast.makeText(getApplicationContext(), "Saved!", Toast.LENGTH_SHORT).show();
        		addListeners();
            }
        }
    };
    
    /**
     * Define the Handler that receives messages from the thread and update the progress
     */
    final Handler ssethandler = new Handler() {
        public void handleMessage(Message msg) {
            int total = msg.getData().getInt("total");
            savingDialog.setProgress(total);
            if (total >= 100){
                removeDialog(SETTINGTOP_DIALOG);
				Toast.makeText(getApplicationContext(), "Set Wallpaper!", Toast.LENGTH_SHORT).show();
        		addListeners();
            }
        }
    };
    
    /**
     * Define the Handler that receives messages from the thread and update the progress
     */
    final Handler bsethandler = new Handler() {
        public void handleMessage(Message msg) {
            int total = msg.getData().getInt("total");
            savingDialog.setProgress(total);
            if (total >= 100){
                removeDialog(SETTINGBOTTOM_DIALOG);
				Toast.makeText(getApplicationContext(), "Set Wallpaper!", Toast.LENGTH_SHORT).show();
        		addListeners();
            }
        }
    };
    
    /**
     *  Define the Handler that receives messages from the thread and update the progress
     */
    final Handler bhandler = new Handler() {
        public void handleMessage(Message msg) {
            int total = msg.getData().getInt("total");
            savingDialog.setProgress(total);
            if (total >= 100){
                removeDialog(SAVINGBOTTOM_DIALOG);
				Toast.makeText(getApplicationContext(), "Saved!", Toast.LENGTH_SHORT).show();

            }
        }
    };

    /** 
     * Nested class that performs progress calculations (counting) 
     */
    private class ProgressThread extends Thread {
        Handler mHandler;
        int height;
        int width;
       
        ProgressThread(Handler h, int height, int width) {
            mHandler = h;
            this.height = height;
            this.width = width;
        }
       
        public void run() {
        	
        	// if we've reached population of selected, crossover and mutate.
        	if (counter == POP_SIZE){
        		temp_wallpapers.clear();
        		adView.requestFreshAd();
        		saveToDB();
        		crossover();
        		mutation();
        		counter = 0;
        	}
        	// Make two thumbnails. 
        	// Set nodes that were choose to universal variables to keep track of which ones were selected.
            for (int r = 0; r < 2; r++){
            	nodes[r] = getNode();
            	bMap[r] = makeBitmap(nodes[r], r, 50, 50, height, width);         	
            }
            Message msg = mHandler.obtainMessage();
            Bundle b = new Bundle();
            b.putInt("total", 100);
            msg.setData(b);
            mHandler.sendMessage(msg);

        }
        
        /**
         * For each pixel, get rgb values and create pixels array. Shift integers to right argb place.
         * @param nodes what functions to use
         * @param r the top or bottom image
         * @param a scale of first half
         * @param t size of first half
         * @param height size of the image
         * @param width size of the image
         * @return pixels = alpha always set to high opacity=1, r value, g value, b value.
         */
        public Bitmap makeBitmap(int[] nodes, int r, int a, int t, int height, int width) {
			Log.d("makeBitmap", nodeToString(nodes));
            int[] pixels = new int[width * height];
            int[] rgbvalues;
            int[] values = new int[NODELENGTH + 2];
            int y = 0, x = 0, index = 0;
            int mh = wm.getDesiredMinimumHeight();
            int mw = wm.getDesiredMinimumWidth();
        	for (y = 0, index = 0; y < height; y++){
        		for (x = 0; x < width; x++){
        			rgbvalues = rgbvalues((int)((y / (double)height) * mh), (int)((x / (double)width) * mw), nodes, values);
        			pixels[index++] = ((0xff<<24) | ((rgbvalues[0])<<16) | ((rgbvalues[1])<<8) | rgbvalues[2]);
        		}       	
        	
	            Message msg = mHandler.obtainMessage();
	            Bundle b = new Bundle();
	            b.putInt("total", (int)(a * (r) + t * (y / (double)height)));
	            msg.setData(b);
	            mHandler.sendMessage(msg);
        	}	
        	
        	Bitmap bMap1 = Bitmap.createBitmap(pixels, width, height, Bitmap.Config.valueOf("ARGB_8888"));
        	return bMap1;    	
        }
    }  
    
    /**
     * If saving is selected for wallpaper, create larger image and 
     * save to SD card. Takes little over 30 seconds. Um.
     */
    private class SavingThread extends ProgressThread {
       
    	int which;
    	boolean wall;
    	
        SavingThread(Handler h, int which, int height, int width, boolean wall) {
            super(h, height, width);
            this.which = which;
            this.wall = wall;
        }
       
        public void run() {
			try {
				long s = 0;
				SQLiteDatabase db = nodeData.getReadableDatabase();
				ContentValues values = new ContentValues();
				values.put(EventDataSQLHelper.LASTSAVE, nodeToString(nodes[which]));
				try {				
					s = db.insertOrThrow(EventDataSQLHelper.SAVE_TABLE, null, values);
					Log.d("AddToSaveDB", nodeToString(nodes[which]));
				} catch (SQLException e) {
					Log.d("AddToSaveDB", "" + e.getMessage());
				}
				db.close();
				
				String filename = "wall" + s + ".png";
			    File path = Environment.getExternalStorageDirectory();
				File gdir = new File(path, "wizard/");
				gdir.mkdirs();
				File file = new File(gdir, filename);
				FileOutputStream out = new FileOutputStream(file);
				Bitmap bm = makeBitmap(nodes[which], 2, 0, 100, height, width);
				bm.compress(Bitmap.CompressFormat.PNG, 100, out);
				out.close();
				
				if (wall) {
					wm.setBitmap(bm);
				}
				sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory().getAbsolutePath())));

			} catch (Exception e) {
				Log.e("OOPS", e.toString()); 
			}
            Message msg = mHandler.obtainMessage();
            Bundle b = new Bundle();
            b.putInt("total", 100);
            msg.setData(b);
            mHandler.sendMessage(msg);

        }
    }
    
    /*********************** MENU **************************/
    
    /**
     * Inflates the Options Menu.
     * @param menu The menu which is being inflated.
     * @return boolean
     */
    public boolean onCreateOptionsMenu(Menu menu) {
    	getMenuInflater().inflate(R.menu.menu, menu);
    	return super.onCreateOptionsMenu(menu);
    }
    
    /**
     * Called when an item from the Options Menu is selected.
     * @param item The item which was selected.
     * @return boolean
     */
    public boolean onOptionsItemSelected(MenuItem item) {
    	switch (item.getItemId()) {
    	// If the user wants to save top image
    	case R.id.save1:
    		showDialog(SAVINGTOP_DIALOG);   	
    		return true;
    	// If user wants to save bottom image
    	case R.id.save2:
    		showDialog(SAVINGBOTTOM_DIALOG);   	
    		return true;
    	case R.id.set1:
    		showDialog(SETTINGTOP_DIALOG);   	
    		return true;
    	// If user wants to save bottom image
    	case R.id.set2:
    		showDialog(SETTINGBOTTOM_DIALOG);   	
    		return true;
    	case R.id.wipe:
    		wipeDB();
    		wallpapers.clear();
    		temp_wallpapers.clear();
    		fillWallpaper();
    		counter = 0;
    		resetImages();
    		return true;
    	case R.id.help:
    		showHelp(null);
    		return true;
    	default:
    		return false;
    	}
    }
    
    /**
     * Displays the Help Dialog box. Depending on if it is the first time a user sees the window, the click listener
     * will either reset the images, or do nothing.
     * @param cl the ClickListener for the ok button
     */
    public void showHelp(OnClickListener cl) {
		Builder adb = new AlertDialog.Builder(this);
		adb.setIcon(R.drawable.icon);
    	adb.setTitle("Wallpaper Wizard");
    	adb.setMessage(Html.fromHtml("<b>Tap</b> the images you like, and I will " + 
    			"learn your preferences to suggest new images.<p>" + 
    			"<b>Press and Hold</b> an image to set it as your wallpaper " + 
    			"and save it to the 'wizard' directory on your SD card. " + 
    			"<p>All proceeds from ads will benefit the computer science " + 
    			"program at <b>Centenary College of Louisiana</b>."));
    	adb.setPositiveButton("OK", cl);
    	adb.show();    	
    }
    
    /**
     * Displays the Save Dialog box. 
     */
    public void showSave(final int which) {
		Builder adb = new AlertDialog.Builder(this);
		adb.setIcon(R.drawable.icon);
    	adb.setTitle("Wallpaper Wizard");
    	adb.setMessage("Good Choice! Would you like to set this as your wallpaper, " + 
    			"or save it to the gallery?");
    	adb.setPositiveButton("Set", new OnClickListener() { 

    		@Override
    		public void onClick(DialogInterface arg0, int arg1) {
    			if (which == TOP) {
    				showDialog(SETTINGTOP_DIALOG);
    			} else {
    				showDialog(SETTINGBOTTOM_DIALOG);
    			}
    		}});
    	adb.setNeutralButton("Save", new OnClickListener() { 

    		@Override
    		public void onClick(DialogInterface arg0, int arg1) {
    			if (which == TOP) {
    				showDialog(SAVINGTOP_DIALOG);
    			} else {
    				showDialog(SAVINGBOTTOM_DIALOG);
    			}
    		}});
    	adb.setNegativeButton("Back", null);
    	adb.show();    	
    }
}
